package com.javaspeak.concurrency.lock.countdownlatch;

import java.util.Random;
import java.util.concurrent.CountDownLatch;

import org.apache.log4j.Logger;

/**
 * This job does not do much. It sleeps a random amount of 0 to 6 seconds.
 * <p>
 * However when it has finished doing its work (sleeping) it calls 
 * countDownLatch.countDown(). 
 * <p>
 * The CountDownLatch is initialised by the JobRunner with a value equal to 
 * the number of threads (initialized via the constructor).  
 * <p>
 * The JobRunner starts all the jobs and then waits for them all to finish 
 * before printing to the console how long it took to run all the jobs.  It 
 * waits for the jobs it spawned to complete by calling the await() method of 
 * the countDownLatch. 
 * <p>
 * For an example, lets say the CountDownLatch was initialised with a value of 
 * 10:
 * <p>
 *     CountDownLatch countDownLatch = CountDownLatch( 10 );
 * <p>
 * This means that if the jobRunner is blocking on the countDownLatch:
 * <p>
 *     countDownLatch.await()
 * <p>
 * that it will unblock and resume execution after countDownLatch.countDown()
 * has been called 10 times by one or more other threads.
 * <p>
 * CountDownLatch is useful in the situation when a parent thread spawns 
 * children threads and wants to wait until the children threads have finished 
 * their execution before resuming its execution.
 * 
 * @author John Dickerson
 */
public class Job implements Runnable {
    
    Logger logger = Logger.getLogger( Job.class );

    private CountDownLatch countDownLatch;
    private Random random;
    
    public Job( CountDownLatch countDownLatch, Random random ){
        
        this.countDownLatch = countDownLatch;
        this.random = random;
    }
    
    @Override
    public void run() {
        
        // do some job
        try {
            int randomInt = random.nextInt( 7 ) * 1000;
            logger.debug( Thread.currentThread().getName() + 
                    ", randomInt : " + randomInt );
            
            Thread.sleep( randomInt );
        }
        catch( InterruptedException e ){
            // do nothing
        }
        
        // Finished job.  Reduce count on countDownLatch.  Note that when
        // the counts have been reduced to zero by all the threads calling
        // countDown a sufficcient number of times, then the thread being 
        // blocked by countDownLatch.await() will resume execution.
        countDownLatch.countDown();
    }

}
